By Shredplayer
Contents
The IUnknown and IDispatch Interfaces
Calling a Method With No Arguments
Getting and Setting properties
Passing and Omitting optional arguments to methods
Using Exposed Objects and Properties from Installed Programs
ProgID’s (Programmatic Identifiers)
Exposing Methods and Properties
Windows Management Instrumentation (WMI)
Connecting to root\default namespace
In this tutorial you will learn how to take advantage of COM(Component Object Model) via scripts.
our purpose here is to use existing COM objects within the Operating System or COM objects from installed
software that we can use to enhance Scripts.
COM is a binary standard for software object interaction. This allows any two components to communicate
regardless of what machine or operating systems , as long as it supports COM and it also doesn’t matter
what language the components are written in, C++,Visual Basic etc.
COM objects are well encapsulated. You cannot gain access to the internal implementation of the object;
you have no way of knowing what data structures the object might be using. But can we Communicate?
the answer is YES through the Interface(IDispatch and IUnknown), it’s the only way to access COM objects.
Simply because you can create identifiers for your scripts which isn’t built-in to mIRC or it offers added
functionality than the built-in identifier.
Below are usage and syntax:
/comopen name Progid
This opens a COM connection to object progid ie. Excel.Application, and assigns the connection a name.
Name – can be anything you want.
Progid – (Programmatic Identifier) Excel.Application.
Excel - Type Library
Application - Object
A type library is a file or part of a file that describes the type of one or more objects. Type libraries do not
store objects they store type information.
/comclose name
This closes the specified COM connection.
/comreg -u filename
This registers/unregisters a COM DLL with windows.
$comerr
This should be checked after a call to any COM command or identifier. Returns 1 if there was an error, 0 otherwise.
comopen name progid
if ($comerr) { command }
$com(name,member,method,type1,value1,...,typeN,valueN)
This calls a member of an open COM connection with the specified methods and parameters.
name - connection name.
member - member name.
methods - Combination of the following values added together:
Methods |
Value |
Description |
DISPATCH_METHOD |
1 |
Executes or Invokes a method. |
DISPATCH_PROPERTYGET |
2 |
Gets a property. |
DISPATCH_PROPERTYPUT |
4 |
Sets a property . |
DISPATCH_PROPERTYPUTREF |
8 |
Sets a property by a reference assignment rather than a value assignment. This is valid only when the property accepts a reference to an object. |
The only thing that differs Scripting Languages from one another is Syntax but implementation may differ,
it’s functionality is still the same.
[JScript]
function DeleteFile(filespec)
{
var fso;
fso = new ActiveXObject("Scripting.FileSystemObject");
fso.DeleteFile(filespec);
}
[VBScript]
Sub DeleteFile(filespec)
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
fso.DeleteFile(filespec)
End Sub
[mIRC]
fso {
comopen fso Scripting.FileSystemObject
var %fso = $com(fso,DeleteFile,1,string,filespec)
comclose fso
}
Unlike programming languages, scripting languages including mSL(mIRC Scripting Language)
(wow I like the sound of that) do not force you to specify a return data type because variables are
automatically cast to the appropriate data type, VBScript on the other hand uses the same data type
for variables, Variant.
The characteristic of a variable that determines what kind of data it can hold.
Type |
Description |
i1 |
1-byte signed integer. see Issues |
i2 |
2-byte signed integer (-32768 to 32767). |
i4 |
4-byte signed integer ( -2147483648 to 2147483647). |
ui1 |
1-byte unsigned integer (0 to 255). |
ui2 |
2-byte unsigned integer (0 to 65535). |
ui4 |
4-byte unsigned integer (0 to 4294967295). |
int |
Integer (-2147483648 to 2147483647). |
uint |
Unsigned integer (0 to 4294967295). |
r4 |
Real, 4-byte floating point number (1.17549435E-38 to 3.40282347E+38). |
r8 |
Double real, 8-byte floating point number (2.2250738585072014E-308 - 1.7976931348623157E+308). |
cy |
A currency number stored as an 8-byte (-922337203685477.5625 to 922337203685477.5625). |
date |
Contains date and time, stored as an 8-byte floating-point number. |
decimal |
This data type indicates numeric data with a fixed precision and scale.
0 through
+/-79,228,162,514,264,337,593,543,950,335 with no decimal point;
right of the decimal; smallest
nonzero number is |
bool |
Can contain any string or numeric representation. see Boolean |
bstr |
Basic string , This data type indicates a null-terminated Unicode character string. |
variant |
Can contain string, date, time, Boolean, or numeric values. |
dispatch |
This data type indicates a pointer to an IDispatch interface. |
unknown |
This data type indicates a pointer to an IUnknown interface. |
error |
This data type indicates a 32-bit error code. |
legend: I = integer , R = real , U = unsigned
Some issues regarding the range of variable types.
Signed i1 as far as i know ranges to -128 to 127, since this is a signed integer it must handle
an optional sign but testing shows it cannot handle (-) sign and the range is the same as
the unsigned ui1 (0 to 255). since this hasn't been resolve yet so i1 will only handle integers
ranging from 0 to 255.
the sample below can test how much data a variable can handle.
syntax: $datatest(variable type,value)
datatest {
; we'll
use Shell.Application for reference only.
comopen c Shell.Application
; since this is
only for reference we omits the member value and assigns the variable a name.
var %i = $com(c, , 1,$1 var, $2)
%i = $com(c,var)
return %i
}
Note: This was tested on mIRC 6.16
Strings - A data type consisting of a sequence of contiguous characters that represent the characters
themselves rather than their numeric values.
BSTR - a pointer to a null-terminated Unicode character array that is preceded by a 4-byte length field.
Technically BSTR and Strings are not the same(as far as VB is concern), BSTR is a pointer to the unicode
character array while Strings are unicode character arrays. This can be confusing but that doesn’t concern us
much since both will work, it's now depends on what you want to use.
Boolean - can be any valid string or numerical value.
Numeric representation - FALSE = 0 and TRUE != 0
$com(name,member,method,bool,0) is FALSE
$com(name,member,method,bool,-1) is TRUE
String representation - TRUE = TRUE and FALSE != TRUE
$com(name,member,method,bool,TRUE) is TRUE
$com(name,member,method,bool, ANY NON TRUE STRING) is FALSE
Note: Every programming & scripting languages have different numerical representation of boolean.
though this isn't a big issue as a personal advice you should restrict usage of boolean variables to
the logical values (TRUE & FALSE) and not rely on equivalent numeric values.
Signed
and Unsigned Integers
all integer types come in two varieties, signed and unsigned.
Signed integers are either negative
or positive and Unsigned integers are always positive.
Signed : 128 , -127, -256
Unsigned : 1, 255, 65535
$com(name/N,varname)
Returns value of the specified variable name.
$comcall(name,alias,...)
$comcall() uses the same format as $com() apart from the alias. It is multi-threaded so it will not halt the script and
will call the specified alias once the call returns.
$comval(name,N,member)
Returns member value for the Nth instantiation of the enumerated collection in name.
$com(name/N)
Returns name if connection is open, or name of Nth connection. N = 0 returns number of open connections.
Properties: progid, dispatch, unknown, result, error, errortext, argerr
progid - object name.
dispatch – boolean value when dispatch pointer exists.
unknown – boolean value when unknown pointer exists.
result - the value returned by the COM object member after the call.
argerr - Nth position of the argument that caused the error, if the error was due to an invalid variable type,
arguments are stored in an array and in reverse order, so the first argument is the one with the highest
index in the array.
ex:
This syntax has 3 arguments $com(name,member,method,[arg1] [arg2] [arg3]) if you supplied invalid
arguments on arg1 its argerr value will be 3 $com(name,member,method,[argerr3] [argerr2] [argerr1])
using argerr can pinpoint which arguments supplied is invalid.
error - error value, if there was an error.
errortext - error description associated with error.
Errortext |
Description |
DISP_E_MEMBERNOTFOUND |
The requested member does not exist, or the call to Invoke tried to set the value of a read-only property.
|
DISP_E_TYPEMISMATCH |
One or more of the parameters could not be coerced. |
DISP_E_UNKNOWNNAME |
One or more of the given names were not known. |
DISP_E_EXCEPTION |
The application needs to raise an exception. |
DISP_E_BADPARAMCOUNT |
The number of elements provided is different from the number of parameters accepted by the method or property. |
DISP_E_PARAMNOTOPTIONAL |
Parameter not optional. |
DISP_E_NOTACOLLECTION |
Does not support a collection. |
DISP_E_BADVARTYPE | One of the parameters is not a valid variant type. |
DISP_E_NONAMEDARGS | Does not support named arguments. |
DISP_E_OVERFLOW | One of the parameters could not be coerced to the specified type. |
DISP_E_PARAMNOTFOUND |
Correct number of parameters was pass but one or more parameters was incorrect. |
DISP_E_UNKNOWNLCID |
The member being invoked interprets string parameters according to the LCID, and the LCID is not recognized. |
DISP_E_UNKNOWNINTERFACE |
The interface identifier passed in riid is not IID_NULL. |
Optional and Non-Optional Arguments
Optional – Indicates that an argument is not required and can be omitted.
Non Optional – argument required by the procedure, omitting will result failure of Com call.
Positional and Named Arguments
Positional Arguments – the supplied arguments must be in order.
VB ex: foo(strName,intAge)
$com(name,member,method,bstr,nick,int,19)
Named Arguments – the supplied arguments can be in any order provided that you pass an argument name followed by
a colon and an equal sign (:=), followed by the argument value.
ex: foo(strName,intAge)
$com(name,member,method,int,intAge:=19,bstr,strName:=nick)
or
$com(name,member,method,intAge:=19,bstrName:=nick)
this is not implemented in mIRC, im just showing you how it might look like.
The IUnknown and IDispatch Interfaces
IUnknown interface lets clients get pointers to other interfaces on a given object.
IDispatch interface exposes objects, methods and properties.
a GetFile method that returns a File object corresponding to the file in a specified path.
Attributes property determines whether the attributes are read-only, system , etc..
Calling a Method With No Arguments
When calling a method with no arguments you only need to pass the connection name, member name
and the DISPATCH_METHOD value and because this does not take any arguments it does not return
any result, hence $com(name).result is not needed; See the example below.
Example:
CascadeWindows {
comopen Cascade Shell.Application
; Cascade – Name
; Shell – Type Library
; Application – Object
; this echoes and will halt the process if connection has failed.
if ($comerr) { echo comopen failed | halt }
; DISPATCH_METHOD (1) invokes the method.
echo Com: $com(Cascade,CascadeWindows,1)
comclose Cascade
}
Getting and Setting Properties
Properties are accessed by passing property name and adding DISPATCH_PROPERTYGET or
DISPATCH_PROPERTYPUT values to DISPATCH_METHOD.
Every DISPATCH_PROPERTYPUT must define at least one argument.
Example:
Ie {
comopen ie InternetExplorer.Application
if ($comerr) { echo comopen failed | halt }
; Getting a property.
; add DISPATCH_METHOD value to DISPATCH_PROPERTYGET.
; 1 + 2 = 3
echo Com: $com(ie,FullName,3)
echo Result: $com(ie).result
; Setting a property.
; add DISPATCH_METHOD value to DISPATCH_PROPERTYPUT.
; 1 + 4 = 5
; this will remove the StatusBar(0 = visible, 1 = Hidden)
echo Com: $com(ie,StatusBar,5,i1,0)
; sets Visible property
echo Com: $com(ie,Visible,5,i1,1)
comclose ie
}
Passing and Omitting Optional Arguments to Methods
You can pass only those arguments that you really need and omit some of the optional arguments
Example:
Popup(Text As String, [SecondsToWait], [Title], [Type])
Notice that the only required argument is the Text and the rest are optional.
$com(name,Popup,3,string,Title)
$com(name,Popup,3,string,Title,i4,0,string,mIRC,i4,2)
but what if you want to omit [SecondsToWait] and pass the remaining arguments?
You just can’t use $com(name,Popup,3,string,Title,string,mIRC,i4,2) it will raise an error.
In automation usually we pass VT_ERROR as the type of the omitted arguments, with the status
code DISP_E_PARAMNOTFOUND(-2147352572) as the value, this error is listed in Winerror.h
-2147352572 run-time error code can be retrieved by assigning a name to error variable.
$com(name,member,method,error varname, ,......)
and using $com(name,varname) to return the error code.
In mIRC, what we can do is to pass error data type and leave the parameter empty and the call
will use the default value declared for that argument, but remember this is only valid for optional arguments.
Popup {
comopen popup Wscript.Shell
if ($comerr) { echo comopen failed | halt }
echo Com: $com(popup,Popup,3,string,Passing and Omitting arguments,i4,0, error, ,i4,2)
echo Result: $com(popup).result
comclose popup
}
Example:
BrowseForFolder(Hwnd As Long, Title As String, Options As Long, [RootFolder])
When the optional arguments [RootFolder] is the last parameter to pass,
We don’t need to pass like this;
$com(name,BrowseForFolder,3,i4,0,string,Title,i4,Options,error, )
All we need is omit the argument;
$com(name,BrowseForFolder,3,i4,0,string,Title,i4,Options)
Hwnd – can be $window(@).hwnd or $dialog(name).hwnd or 0
Text - Text
Options – integer value eg. 512 (removes No New folder button)
Dir – Directory can also be any integer value of Special Folder Constants.
Just replace the string type to i4.
//echo $BrowseForFolder(0,Select Folder,512,$mircdir) – passes all arguments.
//echo $BrowseForFolder(0,Select Folder,512) – omits last argument.
BrowseForFolder {
comopen
BFF Shell.Application
if ($comerr)
{ echo comopen failed | halt }
echo Com:
$com(BFF,BrowseForFolder,3,i4,$1,string,$2,i4,$3,string,$4,dispatch* Items)
echo
Result: $com(BFF).result
comclose
BFF
if $com(Items)
{
echo Com:
$com(Items,Items,3,dispatch* Item)
echo
Result: $com(Items).result
comclose
Items
}
if $com(Item)
{
echo Com:
$com(Item,Item,3,dispatch* Path)
echo
Result: $com(Item).result
comclose
Item
}
if $com(Path)
{
echo Com
$com(Path,Path,3)
echo Path: $com(Path).result
comclose
Path
}
}
Note: error checking not included in the above code.
Other Properties are available for error checking like IsFileSytem to check if the selected
Folder is a file system folder.
$comval() returns the member value for the Nth Instantiation of the enumerated
collection of instances.
Example:
This will enumerate collection of drives.
EnumDrives {
comopen drives Scripting.FileSystemObject
if ($comerr)
{ echo comopen failed | halt }
echo Com: $com(drives,Drives,3,dispatch* items)
echo Result: $com(drives).result
comclose drives
if $com(items) {
; count the number of drives.
echo Com: $com(items,Count,3)
var %c = $com(items).result,%i = 1
; loop the result.
while (%i <= %c) {
; we pass the Path Property.
echo Drive: $comval(items,%i,Path)
; Other Properties: AvailableSpace, DriveLetter, DriveType, FileSystem, IsReady, RootFolder
; SerialNumber, ShareName, TotalSize, VolumeName.
inc %i
}
comclose items
}
}
Using Exposed Objects and Properties from Installed Programs
This example takes advantage of NERO exposed Objects and Properties, you can burn
Audio CD’s , Image, VCD, etc. basically all of capabilities of the Program can be use.
This of course if Nero is Installed.
Example:
This will Eject then Load CD-ROM Drives.
Nero {
comopen Nero Nero.Nero
if ($comerr) { echo comopen failed | halt }
echo Com $com(Nero,GetDrives,1,i1,0,dispatch* Drive)
echo Com $com(Nero).result
comclose nero
if $com(Drive) {
echo Com $com(Drive,Count,3)
var %c = $com(Drive).result, %i = 1
while (%i <= %c) {
echo Com: $comval(Drive,%i,EjectCD)
echo Com: $comval(Drive,%i,LoadCD)
inc %i
}
comclose Drive
}
}
ProgID’s (Programmatic Identifiers)
ProgID’s are registered on your system registry, The format of a ProgID is <Program>.<Component>.<Version>
separated by periods and with no spaces, as in Word.Document.6, basically we don’t need to specify version
rather we use the version independent ProgID.
By convention, the ProgID is named <Type Library>.<Object>
Steps in finding ProgID’s.
1. Run Regedit
2. Press CTRL+F
3. Enter the word ProgID or VersionIndependentProgID then click Find Next
4. Once a ProgID is found, see if it complies with our ProgID format and you can also test it in mIRC with
/comopen name <ProgID.YouFound> to see if mIRC can open it.
5. Optional. Find the InprocServer32 key nested along the ProgID key and write down it’s associated dll
path for later reference.
6. To keep on finding ProgID’s Press F3
If you’re too lazy to do this check out the ProgiDEnumerator example in the WMI Section.
Exposing Methods and Properties
Methods and Properties can be exposed using Visual Basic Object Browser or if Word and Excel is installed, look
under Tools\Macro\Visual Basic Editor (may differ from versions) or Press ALT+F11 then Press F2 to open
Object Browser, under Tools\References select type libraries of your choice or you can browse the Inprocserver32
path that you found then add it to our references, this will automatically added to the Object Browser. Select the
added type library and Object Methods,Properties and syntax will be exposed.
Object Browser
The Object Browser provides information about the classes, methods, and properties a COM object exposes.
OLE-COM OBJECT VIEWER can also be use if Visual C++\Studio is installed.
Windows Management Instrumentation (WMI)
WMI can be use to manage computer hardware, computer software, and nearly everything in between,
mIRC version 6.16 added $comval() it main task is to return a value of Nth collection of instances.
Get Method
The Get method of the SWbemServices object retrieves an object, either a class definition or an instance,
based on the object path.
Example:
Win32_Processor
CPU {
comopen Locator WbemScripting.SWbemLocator
if ($comerr) { echo comopen failed | halt }
echo Com: $com(Locator, ConnectServer, 3, dispatch* Services)
echo Result: $com(Locator).result
comclose Locator
if $com(Services) {
; Win32_Processor.DeviceID="CPU0" is an Instance of Win32_Processor
echo Com: $com(Services, Get, 3,string, Win32_Processor.DeviceID="CPU0",dispatch* Item)
echo Result: $com(Services).result
comclose Services
}
if $com(Item) {
echo Com: $com(Item,Caption,3)
echo Caption: $com(Item).result
echo Com: $com(Item,Manufacturer,3)
echo Manufacturer: $com(Item).result
; GetObjectText_ can be used to get Object contents or Properties in MOF syntax.
echo GetObjectText_: $com(Item,GetObjectText_,3)
write –c MOF.txt $com(Item).result
run MOF.txt
comclose Item
}
}
GetObjectText_
This returns a textual rendering of the object, and can be used to display an object's contents.
The output format is MOF(Managed Object Format) syntax.
Note: line too long error will be encountered if MOF contents exceed mIRC variable limits.
Getting and Setting Properties
Properties are accessed the same way as we usually accessed a property by passing a property name
and adding the value of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT to DISPATCH_METHOD,
the only thing differs is that we need to use Put_ method to update the changes.
Put_ Method
The Put_ method creates or updates an instance or class object to WMI
You can use this method after you modify any properties or methods and
your changes are written to WMI.
The example below demonstrates that task.
Example:
Win32_LogicalDisk
RenameDisk {
comopen Locator WbemScripting.SWbemLocator
if ($comerr) halt
echo Com: $com(Locator, ConnectServer, 3, dispatch* Services)
echo Result: $com(Locator).result
comclose Locator
if $com(Services) {
echo Com: $com(Services, Get,
3,string*,Win32_LogicalDisk.DeviceID="C:",dispatch* Item)
echo Result: $com(Services).result
comclose Services
}
if $com(Item) {
; gets the VolumeName Property.
echo Com: $com(Item,VolumeName,3)
echo 3 Disk Name: $com(Item).result
; set the VolumeName property to "My
Disk Name"
echo Com: $com(Item,VolumeName,5,string,My Disk name)
; updates the changes made by using
Put_ method.
echo Com: $com(Item,Put_,3)
; gets the new name.
echo Com: $com(Item,VolumeName,3)
echo New name: $com(Item).result
comclose Item
}
}
(*) the asterisk is use to make a variable by reference, this means that mIRC will not create
a new variable and this is helpful in preventing some COM related crashes.
Note: you cannot set to a read-only property.
The InstancesOf method of the SWbemServices object creates an enumerator that returns
the instances of a specified class. The good thing about this is you don’t have to supply
an object path, all we pass is the class name eg. Win32_Service
Example:
Win32_Service
Service {
comopen Locator WbemScripting.SWbemLocator
if ($comerr) { echo comopen failed | halt }
echo Com: $com(Locator,ConnectServer,3, dispatch* Services)
echo Result: $com(Locator).result
comclose Locator
if $com(Services) {
echo com: $com(Services, InstancesOf,3,string,Win32_Service,dispatch* Instances)
echo result: $com(Services).result
comclose Services
}
if $com(Instances) {
echo com: $com(Instances,Count,3)
var %c = $com(Instances).result, %i = 1
while (%i <= %c) {
echo Service: $comval(Instances,%i, DisplayName)
echo State: $comval(Instances,%i, State)
inc %i
}
comclose instances
}
}
WQL is a subset of the ANSI standard Structured Query Language (SQL).
if you're into SQL query you'll be feel at home using WQL since WMI borrowed the technique
from database style query.
simple WQL Query that retrieves all Logical drives
format: SELECT PROPERTIES FROM CLASS
SELECT * FROM Win32_LogicalDisk
using WHERE clause to retrieve logical drives with NTFS filesystem.
format: WHERE <property> <operator> <constant>
or
WHERE <constant> <operator> <property>
SELECT * FROM Win32_LogicalDisk WHERE FileSystem = "NTFS"
or
SELECT * FROM Win32_LogicalDisk WHERE "NTFS" = FileSystem
If a subset of properties is only needed replace the asterisk with desired Properties.
In this way it will only query the property and reduce memory bandwith usage,
and the only accessible property from $comval is the property supplied.
SELECT FileSystem FROM Win32_LogicalDisk WHERE FileSystem = "NTFS"
Note: the query string is not case sensitive.
The ExecQuery method of the SWbemServices object executes a query to retrieve objects.
Example:
This uses ExecQuery where it will only returns the specified Query unlike InstancesOf where it returns all
Instances . The below example only returns disk with NTFS file system.
QueryDisk {
comopen Locator WbemScripting.SWbemLocator
if ($comerr) { echo comopen failed | halt }
echo Com: $com(Locator,ConnectServer,3, dispatch* Services)
echo Result: $com(Locator).result
comclose Locator
if $com(Services) {
echo com: $com(Services, ExecQuery,3,string,SELECT * FROM Win32_LogicalDisk WHERE FileSystem = "NTFS" ,dispatch* Instances)
echo result: $com(Services).result
comclose Services
}
if $com(Instances) {
echo com: $com(Instances,Count,3)
var %c = $com(Instances).result, %i = 1
while (%i <= %c) {
echo Com: $comval(Instances,%i, Name) is $comval(Instances,%i, FileSystem) FileSystem
inc %i
}
comclose instances
}
}
methods can also be pass to $comval just like passing properties.
property - $comval(name,N,property)
method - $comval(name,N,method)
below sample demonstrate the task.
Win32_Printer
Example:
PrintTestPage {
comopen Locator WbemScripting.SWbemLocator
if ($comerr) { echo comopen failed | halt }
echo Com: $com(Locator,ConnectServer,3, dispatch* Services)
echo Result: $com(Locator).result
comclose Locator
if $com(Services) {
; this queries the Win32_Printer
class and will only return the default printer.
echo com: $com(Services, ExecQuery,3,string,SELECT * FROM
Win32_Printer WHERE Default = TRUE,dispatch* Instances)
echo result: $com(Services).result
comclose Services
}
if $com(Instances) {
; echoes the Printer name using
caption property.
echo Default: $comval(Instances,1, Caption)
; Invokes the PrintTestPage method.
echo PrintTestPage: $comval(Instances,1, PrintTestPage)
; return
0 - sucess or 5 - access
denied.
comclose instances
}
}
Unfortunately $comval(name,N,Member) accepts only 3 parameters, it would great if
it would be implemented like this;
$comval(name,N,member,method,...,...)
change the properties through $comval.
eg. $comval(name,N,VolumeName,5,string,My New Volume Name)
Terminate Method
Terminates a process and all of its threads.
The below sample terminates all running process of "Notepad.exe".
Example:
EndProcess {
comopen Locator WbemScripting.SWbemLocator
if ($comerr) { echo comopen failed | halt }
echo Com: $com(Locator,ConnectServer,3, dispatch* Services)
echo Result: $com(Locator).result
comclose Locator
if $com(Services) {
echo com: $com(Services, ExecQuery,3,string,SELECT Name FROM
Win32_Process WHERE Name = "Notepad.exe",dispatch* Instances)
echo result: $com(Services).result
comclose Services
}
if $com(Instances) {
echo Com: $com(Instances,Count,3)
var %c = $com(Instances).result, %i = 1
while (%i <= %c) {
echo Process: $comval(Instances,%i, Terminate)
inc %i
}
comclose instances
}
}
If you’re too lazy finding ProgID on the registry this the thing for you, the Win32_ProgIDSpecification Class
represent any programmatic identifier (ProgID) that needs to be registered during a given installation, this
means that not all ProgID will be enumerated, well at least.
Example:
ProgIDEnumerator {
comopen Locator WbemScripting.SWbemLocator
if ($comerr) { echo comopen failed | halt }
echo Com: $com(Locator,ConnectServer,3, dispatch* Services)
echo Result: $com(Locator).result
comclose Locator
if $com(Services) {
; LIKE "%.%" – it queries ProgID if contains (.)
var %prop = ProgID, Description
echo com: $com(Services, ExecQuery,3,string,SELECT %prop FROM Win32_ProgIDSpecification WHERE ProgID LIKE "%.%",dispatch* Instances)
echo result: $com(Services).result
comclose Services
}
if $com(Instances) {
echo com: $com(Instances,Count,3)
var %c = $com(Instances).result, %i = 1
while (%i <= %c) {
echo ProgID: $comval(Instances,%i, ProgID)
echo Description: $comval(Instances,%i, Description)
inc %i
}
comclose instances
}
}
Operators |
Description |
= |
equal to |
!= or <> |
not equal to |
< |
less than |
> |
larger than |
>= |
larger than or equal to |
<= |
smaller than or equal to |
SELECT - returns instances of the specified class and any of its subclasses
SELECT * FROM CLASS
SELECT * FROM Win32_LogicalDisk
You can also Query desired property by replacing the * (asterisk)
The only property queried will be available to $comval
SELECT property FROM CLASS
SELECT FileSystem FROM Win32_LogicalDisk
Or using multiple properties
SELECT property1, property2, property3 FROM CLASS
But we just can’t use a string with comma(,) this because mIRC will treat it as arguments.
SELECT FileSystem, FreeSpace, Name FROM Win32_LogicalDisk
Using $chr(44) will do or set a variable.
%var = FileSystem, FreeSpace, Name
SELECT %var FROM Win32_LogicalDisk
WHERE - The WHERE clause is made up of a property or keyword, an operator, and a constant.
SELECT * FROM CLASS WHERE <property> <operator> <constant>
SELECT * FROM CLASS WHERE <constant> <operator> <property>
SELECT * FROM Win32_LogicalDisk WHERE Name = "C:"
or
SELECT * FROM Win32_LogicalDisk WHERE "C:" = Name
OR - Combines two conditions.
This will query if name is C: or D:
SELECT * FROM Win32_LogicalDisk WHERE Name = "C:" OR Name = "D:"
AND
Will query if FileSystem is equal to NTFS and Quota is disabled.
SELECT * FROM Win32_LogicalDisk WHERE FileSystem = "NTFS" AND QuotasDisabled = TRUE
IS - Comparison operator used with NOT and NULL.
Returns Instance if FileSystem IS NULL
SELECT * FROM Win32_LogicalDisk WHERE FileSystem IS NULL
IS NOT
Returns Instance if FileSystem IS NOT NULL.
SELECT * FROM Win32_LogicalDisk WHERE FileSystem IS NOT NULL
The IS and IS NOT operators are valid in the WHERE clause only if the constant is NULL.
LIKE - The LIKE operator determines whether or not a character string matches a specified pattern.
[] - Any one character within the specified range ([a=f]) or set ([abcdef]).
^ - Any one character not within the range ([^a=f]) or set ([^abcdef].)
% - Any string of 0 (zero) or more characters.
_ - Any one character. Any literal underscore used in the query string must be escaped
by placing it inside [] (square brackets).
SELECT * FROM Win32_LogicalDisk WHERE FileSystem LIKE "%NTFS%"
If the query includes _(underscore) enclosed it with [] escape characters because
underscores are meta characters.
In this example it queries if the VolumeName is like _Disk
SELECT * FROM Win32_LogicalDisk WHERE VolumeName LIKE "%[_]Disk%"
Multiple _(underscore)
SELECT * FROM Win32_LogicalDisk WHERE VolumeName LIKE "%[_][_]Disk%"
Multiple Operators
SELECT * FROM Win32_LogicalDisk WHERE (Name = "C:" OR Name = "D:")
AND FreeSpace > 10000000 AND DriveType = 3
ASSOCIATORS OF - retrieves all instances that are associated with a particular source instance.
ASSOCIATORS OF {ObjectPath}
ASSOCIATORS OF {Win32_LogicalDisk.DeviceID="C:"}
We can’t use { } so we set a variable.
%var = {Win32_LogicalDisk.DeviceID="C:"}
ASSOCIATORS OF %var
NULL - Indicates an object does not have an explicitly assigned value.
FALSE - Boolean operator.
TRUE - Boolean operator.
NOT - Comparison operator.
Connecting to root\default namespace
So far all we tried is Providers located in root\cimv2 namespace which is the default namespace when arguments
are omitted in the ConnectServer Method, don' be confused with the name root\default because in WMI scripting
the default namespace is root\cimv2.
ConnectServer([strServer As String = "."], [strNamespace As String], [strUser As String], [strPassword As String],
[strLocale As String], [strAuthority As String], [iSecurityFlags As Long], [objWbemNamedValueSet As Object])
$com(name,ConnectServer,3,dispatch* var)
in this sample we omitted all optional arguments including strNamespace, this is ok but this will default to
root\cimv2 namespace and most providers resides on this namespace but other providers like System restore
resides at root\default and we just can't use those providers if we omits the namespace argument.
so what we'll do is provide a namespace.
$com(name,ConnectServer,3,string,<myServer>,string,root\default, dispatch* var)
we pass server name to connect with the namespace specified, in this case root\default.
or we omits the server name by passing error data type and leave the parameter empty.
$com(name,ConnectServer,3,error, ,string, root\default ,dispatch* var)
Below sample uses System Restore to enumerate restore points available.
Example:
RestorePoints {
comopen Locator WbemScripting.SWbemLocator
if ($comerr) { echo comopen failed | halt }
; connects to root\default
Namespace.
echo Com: $com(Locator,ConnectServer,3,error, ,string, root\default,
dispatch* Services)
echo Result: $com(Locator).result
comclose Locator
if $com(Services) {
echo com: $com(Services, ExecQuery,3,string,SELECT Description FROM
SystemRestore,dispatch* Instances)
echo result: $com(Services).result
comclose Services
}
if $com(Instances) {
echo Com: $com(instances,Count,3)
var %c = $com(instances).result,%i = 1
while (%i <= %c) {
echo Result: $comval(instances,%i, Description)
inc %i
}
comclose instances
}
}
WMI queries tends to eat system resources specially when enumerating large amount of data,
if possible avoid using InstancesOf and use ExecQuery Instead.
Windows provides WMI tools like wbemtest.exe, see your documentation if it is installed.
WMI Tester (wbemtest.exe)
is a general-purpose, graphical tool for interacting with the WMI infrastructure.
1. run wbemtest.exe
2. Click Connect button to open Connect dialog.
3. If Namespace value is root\default, Change the Namespace field's value to root\cimv2 and click the Connect
dialog's Connect button to return to the main WMI Tester window.
4. Click Enum Classes… to open the Superclass Info dialog.
5. In the Superclass Info dialog, leave the Enter superclass name field blank, click the Recursive option, and
click OK to enumerate all CIM classes defined in the root\cimv2 namespace.
6. Scroll down the Query Result dialog until you reach the Win32 Class, and double-click the class name you
want to open eg. Win32_Process
7. Select the Hide System Properties check box to hide the system properties, remaining Win32_Process
properties represent the information you can retrieve from the processes running on a local computer.
The Object editor dialog reveals the definition and implementation details (properties and methods) of the
selected class.
8. Click Instances button to show the Instances available, eg: Win32_Process.Handle=”0”
This is only a thin slice of what COM is all about Particularly WMI, for a start there’s Lot of libraries you can play with,
like WIA(Windows Image Acquisition) , WMP (Windows Media Player) Library etc..
NOTE:
This tutorial is based on my knowledge on VBScript and Jscript, some part of the tutorial may or may not work
on mIRC versions or OS version, just keep in mind that experimenting will help a lot in understanding how COM
works with mIRC. hope you enjoyed and learned from this tutorial! Good Luck.